package com.atguigu.config;


import com.atguigu.bean.Color;
import com.atguigu.bean.ColorFactoryBean;
import com.atguigu.bean.Person;
import com.atguigu.condition.LinuxCondition;
import com.atguigu.condition.MyImportBeanDefinitionRegistrar;
import com.atguigu.condition.MyImportSelector;
import com.atguigu.condition.WindowsCondition;
import org.springframework.context.annotation.*;

/* //类中组件统一设置。满足当前条件，这个类中配置的所有bean注册才能生效；
@Conditional({LinuxCondition.class})
*/
@Configuration
//@Import导入组件，id默认是组件的全类名，注意这个value也是一个class数组，所以上来就先搞个大括号
@Import(value = {Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

    //spring容器里的bean默认是单例
    /**
     * 只会用到 prototype 或 singleton，后面2个根本不会用到
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST  request
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION	 sesssion
         * @Scope: 调整作用域
         * prototype：多实例的：ioc容器启动并不会去调用方法创建对象放在容器中。而是每次获取的时候才会调用方法创建对象；
         * singleton：单实例的（默认值）：ioc容器启动会调用方法创建对象放到ioc容器中， 以后每次获取就是直接从容器（map.get()）中拿，
         * request：同一次请求创建一个实例  ： 没人用
         * session：同一个session创建一个实例  ： 没人用
     *
     *  懒加载：
     *      也叫延迟加载)   懒加载是专门针对单实例bean来说的）：所以 @Scope("prototype")要注释掉、
     * 		上节课说过单实例bean：默认在容器启动的时候创建对象；
     * 		懒加载意思是：容器启动不创建对象。第一次使用(获取)Bean创建对象，并初始化；以后每次获取的时候就不会再创建了，但每次拿都是单例 ，这是懒加载和prototype的区别。
     */
//    @Scope("singleton")
    @Bean(value = "person")
    @Lazy
    public Person person(){
        /**
         * 这句话是测试，可以用来测试单例和多例（看看这个创建bean的方法，也就是本方法，调用了几次就可以）
         * @Scope单例的时候 ： ioc容器创建的时候，就会实例化了，
         * @Scope多例的时候 ： getBean() 的时候 实例化对象
         */
        System.out.println("给容器中添加Person....");
        return new Person("zhangsan",25);
    }

    /**
     * @Conditional({Condition}) ： 按照一定的条件进行判断，满足条件就给容器中注册bean    可以放在方法上，也可以放在类上。
     *  需求：
     * 如果系统是windows，给容器中注册("bill")
     * 如果是linux系统，给容器中注册("linus")  ，咋实现？
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 48);
    }

    /**
     * 给容器中注册组件；
     * 1）、包扫描@ComponentScans + 组件标注注解（@Controller/@Service/@Repository/@Component）[自己写的类] 看到没，只有加了这些注解的才可以被扫进去，不然谁管你
     * 2）、@Bean[适合于注册导入的第三方包里面的组件，因为你无法在第三方包上写一个@Component啊] 配合@Conditional和@Configuration
     * 3）、@Import[也适合于快速给容器中导入一个组件，就是比@Bean方便一些]
     * 		1）、@Import(要导入到容器中的组件)；容器中就会自动注册这个组件，id默认是全类名
     * 		2）、ImportSelector接口实现类：返回需要导入的组件的全类名数组；
     * 		3）、ImportBeanDefinitionRegistrar接口实现类：手动注册bean到容器中
     * 4）、使用Spring提供的 FactoryBean（工厂Bean）;  spring和其他框架（如mybatis）整合的时候，FactoryBean用的比较多
     * 		1）、默认获取到的是工厂bean调用getObject创建的对象
     * 		2）、要获取工厂Bean本身，我们需要给id前面加一个&
     * 			&colorFactoryBean
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }




}
